Import cal3d

Class CalSkeleton

	Field m_coreSkeleton:CalCoreSkeleton
	Field m_vectorBone:CalBone[]
	Field m_isBoundingBoxesComputed:Bool
	
	
	Method New()
		m_coreSkeleton = Null
		m_vectorBone = New CalBone[0]
		m_isBoundingBoxesComputed = False
	End
	
	Method New(coreSkeleton:CalCoreSkeleton)
	
		m_coreSkeleton = coreSkeleton
		m_vectorBone = New CalBone[0]
		m_isBoundingBoxesComputed = False		
	
		Local vectorCoreBone:CalCoreBone[] = coreSkeleton.getVectorCoreBone()
		
		Local boneCount:Int = vectorCoreBone.Length

		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = New CalBone(vectorCoreBone[boneId])
	
			' set skeleton in the bone instance
			bone.setSkeleton(Self)
	
			' insert bone into bone vector
			m_vectorBone = m_vectorBone.Resize(m_vectorBone.Length+1)
			m_vectorBone[m_vectorBone.Length-1] = bone
		Next
	
	End
	
	
	Method calculateState:Void()
		' calculate all bone states of the skeleton
		Local listRootCoreBoneId:Int[] = m_coreSkeleton.getVectorRootCoreBoneId()
	
		For Local iRootCoreBoneId:Int = 0 To listRootCoreBoneId.Length-1
			m_vectorBone[ listRootCoreBoneId[iRootCoreBoneId] ].calculateState()
		Next
		m_isBoundingBoxesComputed = False		
	End
	
	Method clearState:Void()
		' clear all bone states of the skeleton
		For Local boneId:Int = 0 To m_vectorBone.Length-1
			m_vectorBone[boneId].clearState()
		Next
		m_isBoundingBoxesComputed = False		
	End
	
	Method create:Void(coreSkeleton:CalCoreSkeleton)
		Print "Not Implemented Yet..."
	End
	
	Method getBone:CalBone(boneId:Int)
		Return m_vectorBone[boneId]
	End
	
	Method getCoreSkeleton:CalCoreSkeleton()
		Return m_coreSkeleton
	End
	
	Method getVectorBone:CalBone[]()
		Return m_vectorBone
	End
	
	Method getBoneCount:Int()
		Return m_vectorBone.length
	End
	
	Method lockState:Void()
		' lock all bone states of the skeleton
		For Local boneId:Int = 0 To m_vectorBone.Length-1
			m_vectorBone[boneId].lockState()
		Next		
	End
	
	Method getBoneBoundingBox:CalMinMax(min:CalVector=Null, max:CalVector=Null)
	
		If min = Null Then
			min = New CalVector()
		Endif
		If max = Null Then
			max = New CalVector()
		Endif
	
		If m_isBoundingBoxesComputed = False Then
			calculateBoundingBoxes()
		Endif
	
		Local boneId:Int = 0
		If m_vectorBone.Length > 0 Then
			Local translation:CalVector = m_vectorBone[boneId].getTranslationAbsolute()
	
			min.assign(translation)
			max.assign(translation)
	
			boneId = boneId + 1
		Endif
	
		For boneId = boneId To m_vectorBone.Length-1
			Local translation:CalVector = m_vectorBone[boneId].getTranslationAbsolute()
	
			If translation.x > max.x Then
				max.x = translation.x
			Elseif translation.x < min.x Then
				min.x = translation.x
			Endif
			
			If translation.y > max.y Then
				max.y = translation.y
			Elseif translation.y < min.y Then
				min.y = translation.y
			Endif
			If translation.z > max.z Then
				max.z = translation.z
			Elseif translation.z < min.z Then
				min.z = translation.z
			Endif
		Next
		Local mnmx:CalMinMax = New CalMinMax
		mnmx.min = min
		mnmx.max = max
		Return 	mnmx
	
	End
	
	Method calculateBoundingBoxes:Void()
		If m_isBoundingBoxesComputed = True Then 
			Return
		Endif
		
		For Local boneId:Int = 0 To m_vectorBone.Length-1 
			m_vectorBone[boneId].calculateBoundingBox()
		Next
		m_isBoundingBoxesComputed = True		
	End
	
	Method getBonePoints:Int(pointBuffer:Float[])
		Local boneCount:Int = m_vectorBone.Length
	
		Local p:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local translation:CalVector = m_vectorBone[boneId].getTranslationAbsolute()
	
			pointBuffer[p    ] = translation.x
			pointBuffer[p + 1] = translation.y
			pointBuffer[p + 2] = translation.z
	
			p += 3
		Next
	
		Return boneCount		
		
	End

	Method getBonePointsStatic:Int(pointBuffer:Float[])
		Local boneCount:Int = m_vectorBone.Length
	
		Local p:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local translation:CalVector = m_vectorBone[boneId].getCoreBone().getTranslationAbsolute()
	
			pointBuffer[p    ] = translation.x
			pointBuffer[p + 1] = translation.y
			pointBuffer[p + 2] = translation.z
	
			p += 3
		Next
	
		Return boneCount		
		
	End
	
	Method getBoneLines:Int(lineBuffer:Float[])
	
		Local boneCount:Int = m_vectorBone.Length
		
		Local p:Int = 0
		Local numLines:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = m_vectorBone[boneId]
	
			Local parentId:Int = bone.getCoreBone().getParentId()
			If parentId <> -1 Then
				Local parent:CalBone = m_vectorBone[parentId]
	
				Local translation:CalVector = bone.getTranslationAbsolute()
				Local translationParent:CalVector = parent.getTranslationAbsolute()
	
				lineBuffer[p    ] = translationParent.x
				lineBuffer[p + 1] = translationParent.y
				lineBuffer[p + 2] = translationParent.z
	
				lineBuffer[p + 3] = translation.x
				lineBuffer[p + 4] = translation.y
				lineBuffer[p + 5] = translation.z
	
				p = p + 6
				numLines = numLines + 1
			Endif
		Next
	
		Return numLines		
	End


	Method getBoneLinesStatic:Int(lineBuffer:Float[])
	
		Local boneCount:Int = m_vectorBone.Length
		
		Local p:Int = 0
		Local numLines:Int = 0
		For Local boneId:Int = 0 To boneCount-1
			Local bone:CalBone = m_vectorBone[boneId]
	
			Local parentId:Int = bone.getCoreBone().getParentId()
			If parentId <> -1 Then
				Local parent:CalBone = m_vectorBone[parentId]
	
				Local translation:CalVector = bone.getCoreBone().getTranslationAbsolute()
				Local translationParent:CalVector = parent.getCoreBone().getTranslationAbsolute()
	
				lineBuffer[p    ] = translationParent.x
				lineBuffer[p + 1] = translationParent.y
				lineBuffer[p + 2] = translationParent.z
	
				lineBuffer[p + 3] = translation.x
				lineBuffer[p + 4] = translation.y
				lineBuffer[p + 5] = translation.z
	
				p = p + 6
				numLines = numLines + 1
			Endif
		Next
	
		Return numLines		
	End

End Class

Class CalMinMax

	Field min:CalVector
	Field max:CalVector

End